package com.lawcheukwing.MagicDroidMouse;

import java.net.InetAddress;
import java.util.Timer;
import java.util.TimerTask;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.graphics.Shader.TileMode;
import android.graphics.drawable.BitmapDrawable;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.os.PowerManager;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.FrameLayout;

import com.illposed.osc.OSCMessage;
import com.illposed.osc.OSCPort;
import com.illposed.osc.OSCPortOut;

/**
 * 
 * @author Law Cheuk Wing
 * 
 */

public class MagicMouseActivity extends Activity {
	//
	private static final String TAG = "MagicMouse";

	//
	private OSCPortOut sender;
	// The Drawing Canvas
	private ButtonDrawingSurface surface;
	//
//	private float xHistory;
	private float yHistory;
	//
	private int lastPointerCount = 0;
	//
	private DisplayMetrics dm = new DisplayMetrics();
	// Wake lock
	private PowerManager.WakeLock lock;
	// sensors
	private SensorManager mSensorManager;
	private SensorEventListener mSensorListener;
	private Sensor mSensorAccelerometer;
	private Sensor mSensorMagnetic;
	private int screenRotation = Surface.ROTATION_0;
	//
	private Point3D accel;
	//
	private Timer tapTimer;
	// Two-finger scroll
	// private float scrollX = 0f;
	private float scrollY = 0f;

	/**
	 * Mouse sensitivity power
	 */
	private double mMouseSensitivityPower;

	private static final float sScrollStepMax = 6f;
	private static final float sScrollStepMin = 45f;
	private static final float sScrollMaxSettingsValue = 200f;

	private float mScrollStep;

	public MagicMouseActivity() {
		super();
	}

	private void enableSensors() {
		if (mSensorManager == null) {
			mSensorManager = (SensorManager) this.getSystemService(SENSOR_SERVICE);
		}

		if (mSensorAccelerometer == null) {
			mSensorAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
			Log.d(TAG, "Accelerometer Sensor: " + mSensorAccelerometer);
		}

		if (mSensorMagnetic == null) {
			mSensorMagnetic = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
			Log.d(TAG, "Magnetic Sensor: " + mSensorMagnetic);
		}

		this.mSensorManager.registerListener(this.mSensorListener, mSensorAccelerometer,
				SensorManager.SENSOR_DELAY_FASTEST);
		this.mSensorManager.registerListener(this.mSensorListener, mSensorMagnetic,
				SensorManager.SENSOR_DELAY_GAME);
	}

	private void disableSensors() {
		if (mSensorManager != null) {
			this.mSensorManager.unregisterListener(this.mSensorListener);
			this.mSensorManager = null;
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see android.app.Activity#onCreate(android.os.Bundle)
	 */
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		Settings.init(this.getApplicationContext());
		// Hide the title bar
		requestWindowFeature(Window.FEATURE_NO_TITLE);
		getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN|WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD|WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON,
				WindowManager.LayoutParams.FLAG_FULLSCREEN|WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD|WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
		if (this.lock == null) {
			Context appContext = this.getApplicationContext();
			// get wake lock
			PowerManager manager = (PowerManager) appContext
					.getSystemService(Context.POWER_SERVICE);
			this.lock = manager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK|PowerManager.ON_AFTER_RELEASE, this
					.getString(R.string.app_name));
			// prepare sensor Listener
			this.mSensorListener = new SensorEventListener() {
				// @Override
				public void onSensorChanged(SensorEvent event) {
					Sensor sensor = event.sensor;
					int type = sensor.getType();
					switch (type) {
					case Sensor.TYPE_ACCELEROMETER:
						onAccelerometer(event.values);
						break;
					//Maybe in the future add magnetic sensor support.
					}
				}

				// @Override
				public void onAccuracyChanged(Sensor sensor, int accuracy) {
					// no use for this
				}
			};

			enableSensors();
			
			// Setup accelerations
			mMouseSensitivityPower = 1 + ((double) Settings.sensitivity) / 100d;
			mScrollStep = (sScrollStepMin - sScrollStepMax)
					* (sScrollMaxSettingsValue - Settings.scrollSensitivity) / sScrollMaxSettingsValue
					+ sScrollStepMax;
			//
			this.accel = new Point3D();
			// UI runnables

			// window manager stuff
			this.getWindow().setFlags(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN,
					WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
		}
		//
		try {
			//
			setContentView(R.layout.magicmouse_layout);
			surface = new ButtonDrawingSurface(this.getApplicationContext());
			FrameLayout container = (FrameLayout) findViewById(R.id.flTouchPad);
			container.addView(surface, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT));
			this.getWindowManager().getDefaultDisplay().getMetrics(dm);
			//
			this.sender = new OSCPortOut(InetAddress.getByName(Settings.ip), OSCPort
					.defaultSCOSCPort());
			//
			this.initTouchpad();
		} catch (Exception ex) {
			Log.d(TAG, ex.toString());
		}
	}

	public boolean onCreateOptionsMenu(Menu menu) {
		super.onCreateOptionsMenu(menu);
		//
		menu.add(0, 1, 0, R.string.txt_reset_sensors).setShortcut('0', 'r');
		menu.add(0, 2, 0, R.string.txt_preferences).setShortcut('1', 'p').setIcon(R.drawable.icon_prefs);
		menu.add(0, 3, 0, R.string.txt_about).setShortcut('3', 'a').setIcon(R.drawable.icon_about);
		//
		return true;
	}
	
	public boolean onOptionsItemSelected(MenuItem item) {
		//
		switch (item.getItemId()) {
		case 1:
			//
			resetSensors();
			resetBias();
			this.minEventTime = 100;
			break;
		case 2:
			//
			this.startActivity(new Intent(this, PrefsActivity.class));
			break;
		case 3:
			//
			this.startActivity(new Intent(this, AboutActivity.class));
			break;
		}
		//
		return super.onOptionsItemSelected(item);
	}

	private void initTouchpad() {
		FrameLayout fl = (FrameLayout) this.findViewById(R.id.flTouchPad);
		// let's set up a touch listener
		fl.setOnTouchListener(new View.OnTouchListener() {
			public boolean onTouch(View v, MotionEvent ev) {
				return onMouseMove(ev);
			}
		});
	}

	public void onStart() {
		super.onStart();
	}

	public void onResume() {
		super.onResume();
		// acquire screen lock
		this.lock.acquire();
		// set sensor
		enableSensors();
		// ensure correct orientation
		setRequestedOrientation(Settings.displayInverted ? ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT : ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
		screenRotation = this.getWindowManager().getDefaultDisplay().getRotation();
	}

	public void onPause() {
		super.onPause();
		// this'd be a great time to disconnect from the server, and clean
		// up anything that needs to be cleaned up.
		// release screen lock
		this.lock.release();
		// release sensor
		disableSensors();
	}

	public void onStop() {
		super.onStop();
	}

	public void onDestroy() {
		super.onDestroy();
		this.sender.close();
	}

	private void resetSensors() {
		this.speed2D = new Point3D();
	}
	private void resetBias() {
		Point3D.copy(this.accel, this.accelerometerBias);
	}

	// mouse events
	boolean isScrolling = false;
	int scrollCount = 0;
	int rightClickAllowance = 1; //scroll iterations before skipping Right Click and doing scroll instead in two touch right click mode
	int leftButtonPointer = -1;
	int rightButtonPointer = -1;
	boolean middleButtonPushed = false;
	private boolean onMouseMove(MotionEvent ev) {
//		float xMove = 0f;
		float yMove = 0f;

		int pointerCount = ev.getPointerCount();

		switch (ev.getActionMasked()) {
		case MotionEvent.ACTION_DOWN:
		case MotionEvent.ACTION_POINTER_DOWN:
			// scrollX = 0;
			scrollY = 0;
			//
			if(pointerCount == 1){
				if(Math.round(dm.widthPixels / 2) > ev.getX()){ //Left button.
					leftButtonPointer = ev.getPointerId(0);
				}else{ //Right button.
					rightButtonPointer = ev.getPointerId(0);
				}
				if(this.tapTimer == null){
					this.tapTimer = new Timer();
				}
				this.tapTimer.scheduleAtFixedRate(new TimerTask() { //Delay button down to allow two-finger scroll.
					public void run() {
						onTimerFired();
					}
				}, Settings.clickTime, 100000); //The big number is to ensure it dosen't have a chance to repeat.
			}else if(pointerCount == 2 && isScrolling == false){
				if(this.tapTimer == null){ //Too long, register as both button down.
					int targetPointerId = ev.getActionIndex();
					if(Math.round(dm.widthPixels / 2) > ev.getX(targetPointerId)){ //Left button.
						if(leftButtonPointer == -1){
							leftButtonPointer = ev.getPointerId(0) == rightButtonPointer ? ev.getPointerId(1) : ev.getPointerId(0);
							leftButtonDown();
						}
					}else{ //Right button.
						if(rightButtonPointer == -1){
							rightButtonPointer = ev.getPointerId(0) == leftButtonPointer ? ev.getPointerId(1) : ev.getPointerId(0);
							rightButtonDown();
						}
					}
				}else{ //Two finger touched simultaneously, may be a scroll, wait to see if there will be one more finger.
					this.tapTimer.cancel();
					this.tapTimer = null;
					leftButtonPointer = -1;
					rightButtonPointer = -1;
					if(this.tapTimer == null){
						this.tapTimer = new Timer();
					}
					this.tapTimer.scheduleAtFixedRate(new TimerTask(){
						public void run() {
							isScrolling = true;
							surface.drawVScrollArrow();
							if(tapTimer != null){
								tapTimer.cancel();
								tapTimer.purge();
								tapTimer = null;
							}
						}
					}, Settings.clickTime, 100000);
				}
			}else if(pointerCount == 3){
				if(this.tapTimer != null) { //Only do a middle button down if the user is fast enough.
					this.tapTimer.cancel();
					this.tapTimer.purge();
					this.tapTimer = null;
					middleButtonPushed = true;
					middleButtonDown();
					surface.drawMiddleButton();
				}
			}
//			xMove = 0;
			yMove = 0;
			scrollY = 0;
			//
//			this.xHistory = ev.getX();
			this.yHistory = ev.getY();
			break;
		case MotionEvent.ACTION_UP:
			if(middleButtonPushed){
				middleButtonUp();
				middleButtonPushed = false;
				surface.drawLR(0f, 0f);
				break; // <--Intentional! Don't change.
			}
		case MotionEvent.ACTION_POINTER_UP:
			if(leftButtonPointer == -1 && rightButtonPointer == -1 && isScrolling == true){ //It is scrolling.
				if(ev.getActionMasked() == MotionEvent.ACTION_UP){ //No more fingers, stop scrolling.
					isScrolling = false;
					surface.drawLR(0f, 0f);
				}
			}else{ //Normal mouse button event.
				if(this.tapTimer != null){ //Lifted the finger too fast, generate a click.
					this.tapTimer.cancel();
					this.tapTimer = null;
					if(leftButtonPointer != -1){ //Left button click.
						leftButtonDown();
						leftButtonUp();
						leftButtonPointer = -1;
					}else if(rightButtonPointer != -1){ //Right button click.
						rightButtonDown();
						rightButtonUp();
						rightButtonPointer = -1;
					}
				}else{ //Timer fired, we only need to send button up.
					if(ev.getActionMasked() == MotionEvent.ACTION_POINTER_UP){ //The gesture is not finished.
						if(ev.getPointerId(ev.getActionIndex()) == leftButtonPointer){
							leftButtonUp();
							leftButtonPointer = -1;
						}else if(ev.getPointerId(ev.getActionIndex()) == rightButtonPointer){
							rightButtonUp();
							rightButtonPointer = -1;
						}
					}else{ //The last finger has lifted.
						if(leftButtonPointer != -1){ //Left button up.
							leftButtonUp();
							leftButtonPointer = -1;
						}else if(rightButtonPointer != -1){ //Right button up.
							rightButtonUp();
							rightButtonPointer = -1;
						}
					}
				}
			}
//			xMove = 0;
			yMove = 0;
			break;
		case MotionEvent.ACTION_MOVE:
			if(leftButtonPointer == -1 && rightButtonPointer == -1 && isScrolling == true) { // Scrolling right now.
				if(pointerCount == 1){ //scrolling with one finger is allowed.
					scrollY += ev.getY() - this.yHistory;
					int dir = 0;
					if (Math.abs(scrollY) > mScrollStep) {
						if (scrollY > 0f) {
							dir = 1;
						} else {
							dir = -1;
						}
						
						if (Settings.scrollInverted) {
							dir = -dir;
						}
						
						scrollY = 0f;
					}
					this.yHistory = ev.getY();
					if(dir != 0) this.sendScrollEvent(dir);
				}else if(pointerCount == 2){ //both finger: more precise control.
					int pointer0 = ev.getPointerId(0);
					int pointer1 = ev.getPointerId(1);
					float posY = ev.getY(pointer0);
					// only consider the second pointer if I had a previous history
					if (lastPointerCount == 2) {
						posY += ev.getY(pointer1);
						posY /= 2;
						yMove = posY - this.yHistory;
					} else {
						yMove = posY - this.yHistory;
						posY += ev.getY(pointer1);
						posY /= 2;
					}
					this.yHistory = posY;
					scrollY += yMove;
					int dir = 0;
					if (Math.abs(scrollY) > mScrollStep) {
						if (scrollY > 0f) {
							dir = 1;
						} else {
							dir = -1;
						}
						if (Settings.scrollInverted) {
							dir = -dir;
						}
						scrollY = 0f;
					}
					if(dir != 0) this.sendScrollEvent(dir);
				}
			}else{
				//Ignore it, this is not a touch pad.
			}
			break;
		}
		lastPointerCount = pointerCount;
		return true;
	}
	
	private void onTimerFired(){
		if(leftButtonPointer != -1){
			leftButtonDown();
		}else{
			rightButtonDown();
		}
		if(this.tapTimer != null){
			this.tapTimer.cancel();
			this.tapTimer = null;
		}
	}
	
	//Sensor

	private void onAccelerometer(float[] values) {
		float tmp;
		switch (screenRotation){
		case Surface.ROTATION_0:
			break;
		case Surface.ROTATION_90:
			tmp = -values[1];
			values[1] = values[0];
			values[0] = tmp;
			break;
		case Surface.ROTATION_180:
			values[0] *= -1;
			values[1] *= -1;
			break;
		case Surface.ROTATION_270:
			tmp = -values[0];
			values[0] = values[1];
			values[1] = tmp;
			break;
		}
		Point3D.copy(values, this.accel);
		this.moveMouseFromSensors();
	}
	
	Point3D oldAccel = new Point3D();
	Point3D speed2D = new Point3D();
	Point3D accelerometerBias = new Point3D();
	long lastEventTime = android.os.SystemClock.uptimeMillis();
	long minEventTime = 100;
	int idleAccelCount = 0;
	
	private void moveMouseFromSensors() {
		if(this.accel.z < 9 || this.accel.z > 11) return;
		long currentEventTime = android.os.SystemClock.uptimeMillis();
		minEventTime = Math.round( (double) (minEventTime + Math.max(0, Math.min(minEventTime, currentEventTime - lastEventTime))) / 2);
		if(currentEventTime - lastEventTime > 100) {
			resetSensors();
		}
		if(Math.sqrt((this.accel.x - this.accelerometerBias.x) * (this.accel.x - this.accelerometerBias.x) + (this.accel.y - this.accelerometerBias.y) * (this.accel.y - this.accelerometerBias.y)) < 0.001){
			idleAccelCount += 1;
			if(idleAccelCount >= 3){
				resetSensors();
				resetBias();
				idleAccelCount = 0;
			}
		}else{
			idleAccelCount = 0;
		}
		double tempX = ((this.accel.x - this.accelerometerBias.x) + (oldAccel.x - this.accelerometerBias.x)) * (double) (Math.max(minEventTime, 1)) / 2000;
		double tempY = ((this.accel.y - this.accelerometerBias.y) + (oldAccel.y - this.accelerometerBias.y)) * (double) (Math.max(minEventTime, 1)) / 2000;
		speed2D.x += Math.abs(tempX) > 0.0001 ? tempX : 0;
		speed2D.y += Math.abs(tempY) > 0.0001 ? tempY : 0;
		this.sendMouseEvent((int) 2, (float) (500 * speed2D.x), (float) (-500 * speed2D.y));
		lastEventTime = currentEventTime;
		Point3D.copy(this.accel, oldAccel);
	}

	// abstract mouse event

	private void sendMouseEvent(int type, float x, float y) {
		//
		float xDir = x == 0 ? 1 : x / Math.abs(x);
		float yDir = y == 0 ? 1 : y / Math.abs(y);
		//
		Object[] args = new Object[3];
		args[0] = type;
		args[1] = (float) (Math.pow(Math.abs(x), mMouseSensitivityPower)) * xDir;
		args[2] = (float) (Math.pow(Math.abs(y), mMouseSensitivityPower)) * yDir;
		OSCMessage msg = new OSCMessage("/mouse", args);
		try {
			this.sender.send(msg);
		} catch (Exception ex) {
			Log.d(TAG, ex.toString());
		}
	}

	private void sendScrollEvent(int dir) {
		Object[] args = new Object[1];
		args[0] = dir;
		//
		OSCMessage msg = new OSCMessage("/wheel", args);
		try {
			this.sender.send(msg);
		} catch (Exception ex) {
			Log.d(TAG, ex.toString());
		}
	}

	private synchronized void leftButtonDown() {
		Object[] args = new Object[1];
		args[0] = 0;
		OSCMessage msg = new OSCMessage("/leftbutton", args);
		try {
			this.sender.send(msg);
		} catch (Exception ex) {
			Log.d(TAG, ex.toString());
		}
		// graphical feedback
		surface.drawLR(1f,(rightButtonPointer != -1)?1f:0f);
	}

	private synchronized void leftButtonUp() {
		Object[] args = new Object[1];
		args[0] = 1;
		OSCMessage msg = new OSCMessage("/leftbutton", args);
		try {
			this.sender.send(msg);
		} catch (Exception ex) {
			Log.d(TAG, ex.toString());
		}
		// graphical feedback
		surface.drawLR(0f,(rightButtonPointer != -1)?1f:0f);
	}

	private synchronized void rightButtonDown() {
		Object[] args = new Object[1];
		args[0] = 0;
		OSCMessage msg = new OSCMessage("/rightbutton", args);
		try {
			this.sender.send(msg);
		} catch (Exception ex) {
			Log.d(TAG, ex.toString());
		}
		// graphical feedback
		surface.drawLR((leftButtonPointer != -1)?1f:0f,1f);
	}

	private synchronized void rightButtonUp() {
		Object[] args = new Object[1];
		args[0] = 1;
		OSCMessage msg = new OSCMessage("/rightbutton", args);
		try {
			this.sender.send(msg);
		} catch (Exception ex) {
			Log.d(TAG, ex.toString());
		}
		// graphical feedback
		surface.drawLR((leftButtonPointer != -1)?1f:0f,0f);
	}

	private synchronized void middleButtonDown() {
		Object[] args = new Object[1];
		args[0] = 0;
		OSCMessage msg = new OSCMessage("/middlebutton", args);
		try {
			this.sender.send(msg);
		} catch (Exception ex) {
			Log.d(TAG, ex.toString());
		}
		// graphical feedback done by the big routine
	}

	private synchronized void middleButtonUp() {
		Object[] args = new Object[1];
		args[0] = 1;
		OSCMessage msg = new OSCMessage("/middlebutton", args);
		try {
			this.sender.send(msg);
		} catch (Exception ex) {
			Log.d(TAG, ex.toString());
		}
		// graphical feedback done by the big routine
	}
	
	// The custom drawing canvas
	
	class ButtonDrawingSurface extends SurfaceView implements SurfaceHolder.Callback {
	    public SurfaceHolder surfaceHolder;
	    private Canvas canvas;
	    Bitmap icon_big;
	    
	    public ButtonDrawingSurface(Context context){
	    	super(context);
	    	surfaceHolder = getHolder();
	    	surfaceHolder.addCallback(this);
	    	Resources r = getResources();
	    	icon_big = ((BitmapDrawable) r.getDrawable(R.drawable.icon_big)).getBitmap();
	    }
	    
	    private void startDrawing(){
	    	canvas = surfaceHolder.lockCanvas();
	    }
	    
	    private void finishDrawing(){
	    	surfaceHolder.unlockCanvasAndPost(canvas);
	    }
	    
	    private void _drawBorder(int r, int g, int b){
	    	canvas.drawARGB(255, 0, 0, 0);
	    	Paint paint = new Paint();
	    	paint.setARGB(255, r, g, b);
	    	int w = canvas.getWidth();
	    	int h = canvas.getHeight();
	    	canvas.drawLine(0.5f, 0.5f, w - 0.5f, 0.5f, paint); //Top
	    	canvas.drawLine(w - 0.5f, 0.5f, w - 0.5f, h - 0.5f, paint); //Right
	    	canvas.drawLine(0.5f, h - 0.5f, w - 0.5f, h - 0.5f, paint); //Bottom
	    	canvas.drawLine(0.5f, 0.5f, 0.5f, h - 0.5f , paint); //Left
	    }
	    
	    private void _drawIcon(){
	    	RectF rectf = new RectF();
	    	int w = canvas.getWidth();
	    	int h = canvas.getHeight();
	    	rectf.left = (w - icon_big.getWidth()) / 2;
	    	rectf.top = h / 2;
	    	rectf.right = ((w + icon_big.getWidth()) / 2);
	    	rectf.bottom = h / 2 + icon_big.getHeight();
	    	canvas.drawBitmap(icon_big, null, rectf, new Paint());
	    }
	    
	    private void _drawButton(float alphaLeft, float alphaRight){
	    	Paint paint = new Paint();
	    	paint.setShader(new LinearGradient(0f, 0f, 0f, canvas.getHeight() / 2f, 0x00ff0000|(Math.round(alphaLeft*255)*0x01000000), 0x00ff0000, TileMode.CLAMP));
	    	canvas.drawRect(1f, 1f, canvas.getWidth() / 2f, canvas.getHeight() / 2f, paint);
	    	paint.setShader(new LinearGradient(0f, 0f, 0f, canvas.getHeight() / 2f, 0x00ff0000|(Math.round(alphaRight*255)*0x01000000), 0x00ff0000, TileMode.CLAMP));
	    	canvas.drawRect(canvas.getWidth() / 2f, 1f, canvas.getWidth() - 1f, canvas.getHeight() / 2f, paint);
	    }
	    
	    private void _drawMidButton(){
	    	Paint paint = new Paint();
	    	paint.setShader(new LinearGradient(0f, 0f, 0f, canvas.getHeight() / 2f, 0xffff0000, 0x00ff0000, TileMode.CLAMP));
	    	canvas.drawRect(canvas.getWidth() * 0.4f, 1f, canvas.getWidth() * 0.6f, canvas.getHeight() / 2f, paint);
    	}
	    
	    private void _drawVScroll(){
	    	Paint paint = new Paint();
	    	paint.setColor(0xffff0000);
	    	paint.setStyle(Paint.Style.FILL);
	    	paint.setAntiAlias(true);
	    	int w = canvas.getWidth();
	    	int h = canvas.getHeight();
	    	Path path = new Path(); //This is the shape we need to draw.
	    	path.moveTo(w * 0.5f, h * 0.1f);
	    	path.lineTo(w * 0.65f, h * 0.2f);
	    	path.lineTo(w * 0.55f, h * 0.2f);
	    	path.lineTo(w * 0.55f, h * 0.4f);
	    	path.lineTo(w * 0.65f, h * 0.4f);
	    	path.lineTo(w * 0.5f, h * 0.5f);
	    	path.lineTo(w * 0.35f, h * 0.4f);
	    	path.lineTo(w * 0.45f, h * 0.4f);
	    	path.lineTo(w * 0.45f, h * 0.2f);
	    	path.lineTo(w * 0.35f, h * 0.2f);
	    	path.close();
	    	canvas.drawPath(path, paint);
	    }
	    
	    public void drawMiddleButton(){
	    	startDrawing();
	    	_drawBorder(255,0,0);
//	    	_drawIcon();
	    	_drawMidButton();
	    	finishDrawing();
	    }
	    
	    public void drawVScrollArrow(){
	    	startDrawing();
	    	_drawBorder(255,0,0);
//	    	_drawIcon();
	    	_drawVScroll();
	    	finishDrawing();
	    }
	    
	    public void drawLR(float left, float right){
	    	startDrawing();
	    	_drawBorder(255,0,0);
//	    	_drawIcon();
	    	_drawButton(left,right);
	    	finishDrawing();
	    }

		@Override
		public void surfaceChanged(SurfaceHolder holder, int format, int width,
				int height) {
			
		}

		@Override
		public void surfaceCreated(SurfaceHolder holder) {
			surfaceHolder = holder;
			drawLR(0f, 0f);
		}

		@Override
		public void surfaceDestroyed(SurfaceHolder holder) {
			
		}
	}
}
